#include "structure/Tower.h"
#include "Constants.h"
#include "TextureMgr.h"
#include <glm/gtc/matrix_transform.hpp>
#include <glm/gtx/transform2.hpp>
#include <glm/gtx/projection.hpp>
#include <math.h>

Tower::Tower(GLuint programHandler, GLShaderConfig shaderConfig, float width, float height) :
	GLStructure(programHandler, shaderConfig),
	width(width),
	height(height),
	columnWidth(TOWER_COLUMN_WIDTH),
	latticeWidth(TOWER_LATTICE_WIDTH),
	topBorder(TOWER_TOP_BORDER),
	topHeight(TOWER_TOP_HEIGHT) {
	column1 = new Cube(programHandler, shaderConfig);
	column2 = new Cube(programHandler, shaderConfig);
	column3 = new Cube(programHandler, shaderConfig);
	column4 = new Cube(programHandler, shaderConfig);

	lattice1 = new Cube(programHandler, shaderConfig);
	lattice2 = new Cube(programHandler, shaderConfig);
	lattice3 = new Cube(programHandler, shaderConfig);
	lattice4 = new Cube(programHandler, shaderConfig);
	lattice5 = new Cube(programHandler, shaderConfig);
	lattice6 = new Cube(programHandler, shaderConfig);
	lattice7 = new Cube(programHandler, shaderConfig);
	lattice8 = new Cube(programHandler, shaderConfig);

	top = new Cube(programHandler, shaderConfig);

	components.push_back(column1);
	components.push_back(column2);
	components.push_back(column3);
	components.push_back(column4);
	components.push_back(lattice1);
	components.push_back(lattice2);
	components.push_back(lattice3);
	components.push_back(lattice4);
	components.push_back(lattice5);
	components.push_back(lattice6);
	components.push_back(lattice7);
	components.push_back(lattice8);
	components.push_back(top);

	column1->setTextureData(TextureMgr::getInstance()->getTowerColumnDiffuseTextureData(), TextureMgr::getInstance()->getTowerColumnDirtTextureData());
	column2->setTextureData(TextureMgr::getInstance()->getTowerColumnDiffuseTextureData(), TextureMgr::getInstance()->getTowerColumnDirtTextureData());
	column3->setTextureData(TextureMgr::getInstance()->getTowerColumnDiffuseTextureData(), TextureMgr::getInstance()->getTowerColumnDirtTextureData());
	column4->setTextureData(TextureMgr::getInstance()->getTowerColumnDiffuseTextureData(), TextureMgr::getInstance()->getTowerColumnDirtTextureData());

	lattice1->setTextureData(TextureMgr::getInstance()->getTowerLatticeDiffuseTextureData(), TextureMgr::getInstance()->getTowerLatticeDirtTextureData());
	lattice2->setTextureData(TextureMgr::getInstance()->getTowerLatticeDiffuseTextureData(), TextureMgr::getInstance()->getTowerLatticeDirtTextureData());
	lattice3->setTextureData(TextureMgr::getInstance()->getTowerLatticeDiffuseTextureData(), TextureMgr::getInstance()->getTowerLatticeDirtTextureData());
	lattice4->setTextureData(TextureMgr::getInstance()->getTowerLatticeDiffuseTextureData(), TextureMgr::getInstance()->getTowerLatticeDirtTextureData());
	lattice5->setTextureData(TextureMgr::getInstance()->getTowerLatticeDiffuseTextureData(), TextureMgr::getInstance()->getTowerLatticeDirtTextureData());
	lattice6->setTextureData(TextureMgr::getInstance()->getTowerLatticeDiffuseTextureData(), TextureMgr::getInstance()->getTowerLatticeDirtTextureData());
	lattice7->setTextureData(TextureMgr::getInstance()->getTowerLatticeDiffuseTextureData(), TextureMgr::getInstance()->getTowerLatticeDirtTextureData());
	lattice8->setTextureData(TextureMgr::getInstance()->getTowerLatticeDiffuseTextureData(), TextureMgr::getInstance()->getTowerLatticeDirtTextureData());

	top->setTextureData(TextureMgr::getInstance()->getTowerTopDiffuseTextureData(), TextureMgr::getInstance()->getTowerTopDirtTextureData());
}

Tower::~Tower() {
	components.clear();

	delete column1;
	delete column1;
	delete column1;
	delete column1;

	delete lattice1;
	delete lattice2;
	delete lattice3;
	delete lattice4;
	delete lattice5;
	delete lattice6;
	delete lattice7;
	delete lattice8;

	delete top;
}

void Tower::updateComponents() {
	glm::mat4 columnTransform = glm::translate(transformationMatrix, glm::vec3(width/2, width/2, height/2));
	columnTransform = glm::scale(columnTransform, glm::vec3(columnWidth, columnWidth, height));
	column1->transform(columnTransform);

	columnTransform = glm::translate(transformationMatrix, glm::vec3(width/2, -width/2, height/2));
	columnTransform = glm::scale(columnTransform, glm::vec3(columnWidth, columnWidth, height));
	column2->transform(columnTransform);

	columnTransform = glm::translate(transformationMatrix, glm::vec3(-width/2, width/2, height/2));
	columnTransform = glm::scale(columnTransform, glm::vec3(columnWidth, columnWidth, height));
	column3->transform(columnTransform);

	columnTransform = glm::translate(transformationMatrix, glm::vec3(-width/2, -width/2, height/2));
	columnTransform = glm::scale(columnTransform, glm::vec3(columnWidth, columnWidth, height));
	column4->transform(columnTransform);

	float latticelong = sqrtf(powf(height/2, 2.0) + powf(width, 2.0)) - latticeWidth;
	float angle = (atan((2*width)/height)) * 180 / PI;

	glm::mat4 latticeTranslate = glm::translate(transformationMatrix, glm::vec3(width/2, 0, height/4));
	glm::mat4 latticeTransform = glm::rotate(latticeTranslate, angle, glm::vec3(1, 0, 0));
	latticeTransform = glm::scale(latticeTransform, glm::vec3(latticeWidth, latticeWidth, latticelong));
	lattice1->transform(latticeTransform);

	latticeTransform = glm::rotate(latticeTranslate, -angle, glm::vec3(1, 0, 0));
	latticeTransform = glm::scale(latticeTransform, glm::vec3(latticeWidth, latticeWidth, latticelong));
	lattice2->transform(latticeTransform);

	latticeTranslate = glm::translate(transformationMatrix, glm::vec3(width/2, 0, height*3/4));
	latticeTransform = glm::rotate(latticeTranslate, angle, glm::vec3(1, 0, 0));
	latticeTransform = glm::scale(latticeTransform, glm::vec3(latticeWidth, latticeWidth, latticelong));
	lattice3->transform(latticeTransform);

	latticeTransform = glm::rotate(latticeTranslate, -angle, glm::vec3(1, 0, 0));
	latticeTransform = glm::scale(latticeTransform, glm::vec3(latticeWidth, latticeWidth, latticelong));
	lattice4->transform(latticeTransform);

	latticeTranslate = glm::translate(transformationMatrix, glm::vec3(-width/2, 0, height/4));
	latticeTransform = glm::rotate(latticeTranslate, angle, glm::vec3(1, 0, 0));
	latticeTransform = glm::scale(latticeTransform, glm::vec3(latticeWidth, latticeWidth, latticelong));
	lattice5->transform(latticeTransform);

	latticeTransform = glm::rotate(latticeTranslate, -angle, glm::vec3(1, 0, 0));
	latticeTransform = glm::scale(latticeTransform, glm::vec3(latticeWidth, latticeWidth, latticelong));
	lattice6->transform(latticeTransform);

	latticeTranslate = glm::translate(transformationMatrix, glm::vec3(-width/2, 0, height*3/4));
	latticeTransform = glm::rotate(latticeTranslate, angle, glm::vec3(1, 0, 0));
	latticeTransform = glm::scale(latticeTransform, glm::vec3(latticeWidth, latticeWidth, latticelong));
	lattice7->transform(latticeTransform);

	latticeTransform = glm::rotate(latticeTranslate, -angle, glm::vec3(1, 0, 0));
	latticeTransform = glm::scale(latticeTransform, glm::vec3(latticeWidth, latticeWidth, latticelong));
	lattice8->transform(latticeTransform);

	glm::mat4 topTransform = glm::translate(transformationMatrix, glm::vec3(0, 0, height - topHeight / 2));
	topTransform = glm::scale(topTransform, glm::vec3(width + topBorder, width + topBorder, topHeight));
	top->transform(topTransform);
}

void Tower::update (glm::mat4 viewMatrix, glm::mat4 modelMatrix) {
	updateComponents();
	TextureMgr::getInstance()->loadTextures(programHandler);
	std::list<GLObject*>::iterator it = components.begin();
	for ( ; it != components.end(); it++ ) {
		(*it)->update(viewMatrix, modelMatrix);
	}
}

